home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / comm2 / mmsmfdcd.lha / MM / Rexx / MM_SMFEDcode.rexx < prev    next >
OS/2 REXX Batch file  |  1996-04-28  |  24KB  |  1,170 lines

  1. /*
  2.  
  3.                     $VER: MM_SMFEDcode.rexx 0.80  (28.04.96)
  4.                           (was renamed from MM_UUout)
  5.  
  6.                            (C) 1995/96 Robert Hofmann
  7.  
  8. */
  9.  
  10. parse arg args
  11.  
  12. options cache
  13. options failat 99
  14. options results
  15.  
  16. signal on break_c
  17. signal on break_d
  18. signal on break_e
  19. signal on break_f
  20. signal on halt
  21. signal on ioerr
  22. signal on syntax
  23.  
  24. address 'MAILMANAGER'
  25.  
  26.  
  27. Main:
  28.  
  29.     call Init
  30.     call Header
  31.     call Parse_Args(args)
  32.     call Read_Cfg
  33.  
  34.     if system.arg.gui    then Show
  35.  
  36.     select
  37.         when system.arg.encode    then call Encode
  38.         when system.arg.decode    then call Decode(system.arg.area, system.arg.msg)
  39.  
  40.         otherwise signal Usage
  41.     end
  42.  
  43. call Quit(0, 'All done.')
  44. exit
  45.  
  46.  
  47. Add_Text: procedure Expose msg.
  48.  
  49.     parse arg line
  50.  
  51.     MM_AddToStem 'msg.text' 'line'
  52.  
  53. return
  54.  
  55.  
  56. break_c:; break_d:; break_e:; break_f:; halt:
  57.     return_code        =    5
  58.     error_line    = 0
  59.     error_msg            = 'Execution halted!!!'
  60.     rc                        = 0
  61. signal Exit
  62.  
  63.  
  64. Check_Pattern: procedure Expose result
  65.  
  66.     arg pattern, string.0
  67.  
  68.     string.count    = 1
  69.     result.                = 0
  70.  
  71.     MM_SearchInStem 'string' 'result' pattern 'STR'
  72.  
  73.     result                = result.0
  74. return result.count>0
  75.  
  76.  
  77. Command: procedure Expose system.
  78.  
  79.     parse arg cmd, noreq
  80.  
  81.     address command cmd; ret = rc
  82.  
  83.     if noreq~=1 & ret>0 then
  84.         do
  85.             call Log('*** WARNING: Command "'cmd'" returned' ret'.')
  86.  
  87.             if system.arg.gui then call Request_Choice('\c\n* * *   W A R N I N G   * * *\n\n"' ||,
  88.                 cmd'"\n\nreturned' ret'!\n', '*  _OK  ', '_')
  89.         end
  90.  
  91. return rc
  92.  
  93.  
  94. Decode: procedure Expose system.
  95.  
  96.   arg area, nr
  97.  
  98.     deldir = 'c:delete >NIL:' system.tmpdir 'all quiet noreq force'
  99.     call Command(deldir, 1)
  100.  
  101.     if ~makedir(strip(system.tmpdir, 't', '/ ')) then call Quit(31, 'Unable to create tmpdir "'system.tmpdir'"!!!')
  102.  
  103.     call Search_Encoded_Files(area, nr, 0, 0)
  104.     call delete(system.tmpfile)
  105.     call Command('c:list >'system.tmpfile system.tmpdir 'lformat "%n %l"')
  106.  
  107.     MM_ReadStem system.tmpfile 'tmp'
  108.     call delete(system.tmpfile)
  109.  
  110.     file.    = 0
  111.     len.    = 0
  112.     note    = 'From:' msg.from '%' msg.fromaddr'; Area:' area
  113.  
  114.     do n=0 to tmp.count-1
  115.         parse var tmp.n    fl ln .
  116.  
  117.     file.max    = max(file.max, length(fl)+2)
  118.         file.n        = fl
  119.         len.max        = max(len.max,    length(ln))
  120.         len.n            = ln
  121.  
  122.         from            = system.tmpdir  || fl
  123.         to                = system.prg.dir || fl
  124.  
  125.         MM_SetFileNote    from 'note'
  126.  
  127.         if exists(to)    then MM_MoveFile to to
  128.  
  129.         MM_MoveFile            from to
  130.  
  131.         call Log('Decoded:' fl ln 'bytes')
  132.     end
  133.  
  134.     file.count    = tmp.count
  135.     len.count        = tmp.count
  136.  
  137.     call Command(deldir)
  138.  
  139.     if system.arg.gui then
  140.         do
  141.             if file.count>0 then
  142.                 do
  143.                     if n>1 then    tmp    = 's were'
  144.                     else                tmp    = ' was'
  145.  
  146.                     text    = '\c\nThe following file'tmp 'decoded from\narea' area', msg #'nr 'to "'system.prg.dir'":\n\n'
  147.                 end
  148.             else text = '\c\nThere were no uuencoded files in this msg!!!\n'
  149.  
  150.             do n=0 to file.count-1
  151.                 text    = text'\1'left(file.n, file.max) || right(len.n, len.max) 'bytes\0\n'
  152.             end
  153.  
  154.           call Request_Choice(text, '*   _OK   ', '_')
  155.         end
  156.  
  157.     if system.ok & system.clearnew then
  158.         do
  159.             flags    = 'READ'
  160.  
  161.             do n=0 to system.msg.count-1
  162.                 MM_EditMsgFlags area system.msg.n 'flags'
  163.             end
  164.  
  165.             MM_Free area
  166.         end
  167.  
  168. return
  169.  
  170.  
  171. Decode_File: procedure Expose system.
  172.  
  173.     parse arg mode, file
  174.  
  175.     olddir    = pragma('d', system.tmpdir)
  176.  
  177.     call Log('Decoding' mode'-encoded file...',, 4)
  178.     ret    = Command(system.cmd.mode.decode)
  179.     call pragma('d', olddir)
  180.  
  181. return ret
  182.  
  183.  
  184. Encode: procedure Expose system.
  185.  
  186.     call Get_Datas
  187.     call Send_File(system.arg.mode)
  188.  
  189. return
  190.  
  191.  
  192. Exit:
  193.  
  194.     select
  195.         when return_code>=40 then error = 'INTERNAL-ERROR:'
  196.         when return_code>=30 then error = 'IO-ERROR:'
  197.         when return_code>=20 then error = 'ERROR:'
  198.         when return_code>=10 then error = 'WARNING:'
  199.         when return_code>=5  then error = 'INFO:'
  200.         otherwise                                    error = ''
  201.     end
  202.  
  203.     if system.arg.gui & return_code>5    then
  204.         do
  205.             tmp    = center(error_msg, max(length(error_msg), 40))
  206.             call Request_Choice('\c\n'error'\n\n\1'tmp'\0\n', '*  _OK  ', '_')
  207.         end
  208.  
  209.   call Log(,, 3)
  210.     call Log('***' strip(error error_msg) '***', '+')
  211.     call Log(,'\',, 3)
  212.  
  213.     call setclip('MM_LogPre', system.mm.logpre)
  214.  
  215. exit return_code
  216.  
  217.  
  218. Expand_Path: procedure
  219.  
  220.     parse arg path
  221.  
  222.     if pos(':', path)+pos('/', path)=0 then path = path(pragma('d')) || path
  223.  
  224. return path
  225.  
  226.  
  227. Get_Addr: procedure Expose msg. system.
  228.  
  229.     if msg.area.data.type~='MAIL' then return ''
  230.  
  231.     parse arg text
  232.  
  233.     ok  = 0
  234.     tmp    = ''
  235.  
  236.     do while ok=0
  237.         tmp = Request_String(text, tmp, 1)
  238.  
  239.         parse var tmp z ':' nt '/' nd '.' p '@' d '.' .
  240.  
  241.         ok        = datatype(z, 'N') & datatype(nt, 'N') & datatype(nd, 'N') & datatype(p, 'N') &,
  242.                         datatype(d, 'A') & upper(d)=msg.domain
  243.         addr    = tmp
  244.     end
  245.  
  246. return addr
  247.  
  248.  
  249. Get_Arg: procedure Expose args system.
  250.  
  251.   arg keyword, mode, old
  252.  
  253.     uargs    = upper(args)
  254.     p            = find(uargs, keyword)
  255.  
  256.     if p=0    then
  257.         do
  258.             p = pos(' 'keyword'=', ' 'uargs)
  259.  
  260.             if p>0 then    args    = overlay(' ', args, p+length(keyword))
  261.  
  262.       p = find(upper(args), keyword)
  263.         end
  264.  
  265.     system.cmdopt.keyword    = p>0
  266.  
  267.     select
  268.         when mode=0    then
  269.             if p>0 then
  270.                 do
  271.                     ret        = 1
  272.                     args    = delword(args, p, 1)
  273.                 end
  274.             else ret    = old
  275.  
  276.         when mode=1 then
  277.             if p>0 then
  278.                 do
  279.                     left    = subword(args, 1, p-1)
  280.                     rest    = subword(args, p+1)
  281.  
  282.                     if left(rest, 1)='"' then    parse var rest . '"'    ret '"'    rest
  283.                     else                                            parse var rest                ret            rest
  284.  
  285.                     args    = strip(left strip(rest))
  286.                 end
  287.             else ret    = old
  288.  
  289.         when mode=2 then
  290.             do
  291.                 if left(args, 1)='"'    then    parse var args . '"'    ret '"'    args
  292.                 else                                                parse var args                ret         args
  293.  
  294.                 if strip(ret)=''            then    ret = old
  295.             end
  296.  
  297.         otherwise exit 99
  298.     end
  299.  
  300.     args    = strip(args)
  301.     ret        = strip(ret, 'b', '" ')
  302.  
  303. return ret
  304.  
  305.  
  306. Get_Datas: procedure Expose msg. system.
  307.  
  308.   MM_GetAddrs                    'system.addr'
  309.     system.addresses  = ''
  310.  
  311.     do n=0 to system.addr.count-1
  312.         system.addresses = system.addresses system.addr.n
  313.     end
  314.  
  315.     upper system.addresses
  316.  
  317.     msg.send    = system.arg.file
  318.     tmp                = 'AREA FLAGS FROM FROMADDR SUBJ TO TOADDR'
  319.  
  320.     do while tmp~=''
  321.         parse var tmp field tmp
  322.  
  323.         msg.field    = '*'
  324.         if system.arg.field~=''    then msg.field    = system.arg.field
  325.     end
  326.  
  327.     if system.arg.gui    then
  328.         do
  329.             call Log('Asking for datas...',, 4)
  330.  
  331.             system.arg.mode    = Request_Choice('What encoding-methode do you want to use?',,
  332.                                                 '_FS-encode|_MIME|_Abort|*_UU-encode', 'FS MIME _ UU')
  333.  
  334.             if system.arg.mode=''    then call Quit(5, 'Aborted by user!')
  335.         end
  336.  
  337.     if system.arg.gui then
  338.         do
  339.             if msg.area='*'    then
  340.                 do
  341.                     MM_AreaReq 'msg.area'
  342.                     if RC~=0    then call Quit(5, 'Aborted by user!')
  343.                 end
  344.  
  345.             do while msg.send='' | ~exists(msg.send)
  346.                 msg.send = path(pragma('d'))
  347.  
  348.                 MM_FileReq 'msg.send'
  349.                 if RC=1    then call Quit(5, 'Aborted by user!')
  350.             end
  351.         end
  352.  
  353.     if ~exists(msg.send)    then call Quit(11, 'Unable to locate "'msg.send'"!')
  354.  
  355.     if system.arg.gui & msg.area=''    then
  356.         do
  357.             MM_AreaReq 'msg.area'
  358.             if RC=1    then call Quit(5, 'Aborted by user!')
  359.         end
  360.  
  361.     MM_GetAreaInfo msg.area 'msg.area.data'
  362.     if RC~=0 then call Quit(11, 'Unknown area "'msg.area'"!')
  363.     msg.domain = Get_Domain(msg.area.data.addr)
  364.  
  365.     if system.arg.gui then
  366.         do
  367.             ret    = Request_Choice('Do you also want to send an introduction-msg?', ' _Use file |_Write now|*  _NO  ', '1 2 0')
  368.  
  369.             select
  370.                 when ret=1    then
  371.                     do
  372.                         system.arg.infofile    = 'ff'x
  373.  
  374.                         do while ~exists(system.arg.infofile)
  375.                             system.arg.infofile = path(system.mm.tempdir)
  376.  
  377.                             MM_FileReq 'system.arg.infofile'
  378.                             if RC=1    then call Quit(5, 'Aborted by user!')
  379.                         end
  380.  
  381.                         system.arg.delinfofile    = Request_Choice('\c\nDelete \1'system.arg.infofile'\0 after posting?',,
  382.                                                                             ' _YES  |*  _NO  ', '1 0')
  383.                     end
  384.  
  385.                 when ret=2 then
  386.                     do
  387.                         system.arg.infofile            = system.tmpfile'.inf'
  388.                         system.arg.delinfofile    = 1
  389.  
  390.                         call Command(replace(system.mm.editor, system.arg.infofile, '%s'))
  391.                     end
  392.  
  393.                 otherwise nop
  394.             end
  395.         end
  396.  
  397.     system.is_mail    = msg.area.data.type='MAIL'
  398.     system.is_echo    = ~system.is_mail
  399.  
  400.     if msg.toaddr='*' then
  401.         if system.is_mail then
  402.             if system.arg.gui then msg.toaddr = Get_Addr('To-Address')
  403.             else call Quit(11, 'To-address missing!')
  404.         else drop msg.toaddr
  405.  
  406.     if msg.to='*'             then
  407.         if system.is_mail    then    msg.to    = Get_Name(msg.toaddr)
  408.         else                            msg.to    = 'All'
  409.  
  410.     if system.arg.gui    then    msg.to    = Request_String('To-name', msg.to, 1)
  411.  
  412.     if msg.fromaddr='*' & system.is_mail then
  413.       if system.arg.gui then
  414.         do
  415.                 MM_GetAddrs 'tmp'
  416.  
  417.                 req.    = 0
  418.  
  419.                 do n=0 to tmp.count-1
  420.                     if Get_Domain(tmp.n)=msg.domain then MM_AddToStem 'req' 'tmp.'n
  421.                 end
  422.  
  423.                 select
  424.                     when req.count=0    then    call Quit(20, 'No valid source-#ADDRESS or #AKA for' system.fromaddr'!!!')
  425.  
  426.                     when req.count=1    then    msg.fromaddr    = req.0
  427.  
  428.                     otherwise
  429.                         do
  430.                       RC         = -99
  431.                             tmp.    = ''
  432.  
  433.                             MM_SingleSelReq 'req' 'tmp' '"Address"' 'STR'
  434.                             if RC=1    then call Quit(5, 'Aborted by user!')
  435.  
  436.                             if tmp.0~=''then  msg.fromaddr = tmp.0
  437.                         end
  438.                 end
  439.             end
  440.         else    msg.fromaddr = msg.area.data.addr
  441.     else        msg.fromaddr = msg.area.data.addr
  442.  
  443.     if msg.from='*'        then    tmp    = Get_Name(msg.fromaddr)
  444.     else                                        tmp    = msg.from
  445.  
  446.     if system.arg.gui    then    tmp = Request_String('From-Name', tmp, 0)
  447.  
  448.     if tmp='' then drop msg.from
  449.     else msg.from = tmp
  450.  
  451.     if msg.subj='*' then
  452.         do
  453.             sfile = msg.send
  454.             p            = lastpos('/', sfile)
  455.             if p>0 then sfile = substr(sfile, p+1)
  456.             p            = lastpos(':', sfile)
  457.             if p>0 then sfile = substr(sfile, p+1)
  458.             tmp        = ''
  459.  
  460.             if system.arg.gui then sfile    = Request_String('Subject', sfile, 1)
  461.  
  462.             msg.subj    = sfile
  463.         end
  464.  
  465.      if system.arg.gui & msg.flags='*' then
  466.         do
  467.             msg.flags    = ''
  468.  
  469.             if system.is_mail then
  470.                 do
  471.                   req.0            = 'CRASH'
  472.                     req.1            = 'HOLD'
  473.                     req.2            = 'KILL'
  474.                     req.3            = 'RRR'
  475.                     req.count    = 4
  476.                 end
  477.             else
  478.                 do
  479.                     req.0            = 'KILL'
  480.                     req.count    = 1
  481.                 end
  482.  
  483.             tmp.            = 0
  484.  
  485.             MM_MultiSelReq 'req' 'tmp' '"Flags"' 'STR'
  486.             if RC=1    & system.mm.release>=449 then call Quit(5, 'Aborted by user!')
  487.  
  488.             do n=0 to tmp.count-1
  489.                 msg.flags    = msg.flags tmp.n
  490.             end
  491.         end
  492.  
  493. return
  494.  
  495.  
  496. Get_Domain: procedure
  497.  
  498.     arg . '@' dmn '.' .
  499. return dmn
  500.  
  501.  
  502. Get_Encoded_File: procedure Expose msg. system.
  503.  
  504.     parse arg mode, area, msgnr, start, ende, open, offs
  505.  
  506.     cont.    = 0
  507.  
  508.     if start=-1    then
  509.         do
  510.             start            = 0
  511.             cont.prev    = 1
  512.         end
  513.  
  514.     if ende=-1    then
  515.         do
  516.             ende            = msg.text.count-1
  517.             cont.next    = 1
  518.         end
  519.  
  520.     if cont.prev    then
  521.         if Search_Encoded(mode, 'BEGIN') then
  522.             if result.0<ende then call Quit(20, 'Could not find end of encoded file!')
  523.  
  524.     if open then
  525.         do
  526.             if ~open(out, system.tmpfile, 'w') then call Quit(30, 'Unable to open "'system.tmpfile'" for write!')
  527.  
  528.             tmp                    = start+offs+1
  529.             msg.enclen    = length(msg.text.tmp)
  530.         end
  531.  
  532.     if ~cont.prev then
  533.         do
  534.             if mode='MIME' then
  535.                 do n=start-2 to start
  536.                     call writeln(out, msg.text.n)
  537.                 end
  538.             else call Write_Line(start, 0)
  539.  
  540.             msg.text.start    = '*** DONE ***'
  541.         end
  542.     else call Write_Line(start, 1)
  543.  
  544.     fail = 0
  545.     last = 0
  546.  
  547.     do n=start+1 to ende-1
  548.         check    = (cont.prev & cont.next) | (n>start+offs & n<ende-2) | (cont.next & n>start+2) | (cont.prev & n<ende-2)
  549.         ret        = Write_Line(n, check)
  550.         fail    = fail+~ret
  551.  
  552.         if ret then
  553.             do
  554.                 fail    = 0
  555.                 last    = n
  556.             end
  557.  
  558.         if fail~=20    then iterate
  559.  
  560.         cont.next    = 0
  561.         ende            = last+1
  562.  
  563.         leave
  564.     end
  565.  
  566.     call Write_Line(ende, cont.next)
  567.     msg.text.ende    = msg.text.start
  568.  
  569.     tmp    = ende+1
  570.     if mode='UU' & upper(left(msg.text.tmp, 4))='SIZE' then    call writeln(out, msg.text.tmp)
  571.  
  572.     if cont.next then
  573.         do
  574.             msgnr    = msgnr+1
  575.  
  576.             if msgnr>system.ainfo.himsg then
  577.                 if mode~='MIME'                        then    call Quit(20, 'Could not find end of encoded file!')
  578.         else                                                        call Write_Line(last+1, 0)
  579.             else
  580.                 do
  581.                     call Read_Msg(area, msgnr, 'Could not find end of encoded file!')
  582.                     call Search_Encoded(mode, 'END')
  583.  
  584.               if result.count=0 then    ende    = -1
  585.                     else                                        ende    = result.0
  586.  
  587.               msgnr    = Get_Encoded_File(mode, area, msgnr, -1, ende, 0, 2)
  588.                 end
  589.         end
  590.  
  591.     if open then    call close(out)
  592.  
  593. return msgnr
  594.  
  595.  
  596. Get_Name: procedure Expose msg. system.
  597.  
  598.     parse arg address
  599.  
  600.   MM_GetNodelistNode address 'tmp'
  601.  
  602.     if rc>0 then
  603.         if find(system.addresses, upper(address))>0 then
  604.             if system.mm.release<429    then do; MM_GetSysop 'ret'; end
  605.             else    ret    = msg.area.data.alias
  606.         else        ret = 'Sysop'
  607.     else            ret = tmp.sysop
  608.  
  609. return ret
  610.  
  611.  
  612. Get_Version: procedure
  613.  
  614.     parse arg mode
  615.  
  616.     parse value sourceline(3-mode) with . . ver .
  617.     parse var ver tst 'ß' .
  618.  
  619.     if ~datatype(strip(tst, 'b', '/ce '), 'N') then
  620.         if ~mode then ver = Get_Version(1)
  621.         else exit 99
  622.  
  623. return ver
  624.  
  625.  
  626. Header:
  627.  
  628.     call Log(,'/',, 3)
  629.     call Log('***' system.prg.id '***', '+')
  630.     call Log(system.prg.cr)
  631.     call Log(,, 3)
  632.  
  633. return
  634.  
  635.  
  636. Include_Lib: procedure
  637.  
  638.     parse arg lib, prio
  639.     if right(upper(lib), 8)~='.LIBRARY' then lib=lib'.library'
  640.     if prio='' then prio=0
  641.  
  642.     if ~show('l', lib) then
  643.         if ~addlib(lib, prio, -30, 0) then
  644.             do
  645.                 say '*** ERROR: Could not open' lib'!!! ***'
  646.                 exit 10
  647.             end
  648. return
  649.  
  650.  
  651. Init:
  652.  
  653.     system.                                    = 0
  654.  
  655.     MM_GetTaskPri                        'system.taskpri'
  656.     call                                        pragma('p', system.taskpri)
  657.  
  658.     system.prg.name                    = 'MM_SMFEDcode'
  659.     system.prg.version            = Get_Version(0)
  660.     system.prg.id                        = system.prg.name 'v'system.prg.version
  661.     system.prg.cr                        = '(C) 1995/96 Robert Hofmann'
  662.     system.prg.cfg                    = 'MM:Config/'system.prg.name'.cfg'
  663.     system.fs.ptrn.begin        =    '"!start #?"'
  664.     system.fs.ptrn.end            = '"!end #[0-9] #?"'
  665.     system.fs.offs.begin        = 1
  666.     system.mime.ptrn.begin  = '"Content-transfer-encoding:#?base64#?"'
  667.     system.mime.ptrn.end         = '"#?="'
  668.     system.mime.offs.begin    = 1
  669.     system.uu.ptrn.begin        =    '"begin #[0-9] #?"'
  670.     system.uu.ptrn.end            = 'end'
  671.     system.uu.offs.begin        = 1
  672.     system.mm.logpre                 = getclip('MM_LogPre')
  673.     system.prg.logpre                = system.mm.logpre'|'
  674.     call                                            setclip('MM_LogPre', system.prg.logpre)
  675.     system.cmdopts                    = 'DECODE/S,ENCODE/S,GUI/S,AREA/K,MSG/K,FILE/K,FLAGS/K,FROM/K,' ||,
  676.                                                         'FROMADDR/K,ORIGIN/K,SUBJ/K,TO/K,TOADDR/K,INFOFILE/K,MODE/K,'    ||,
  677.                                                         'DELINFOFILE/S,MAXSIZE/K/N'
  678.  
  679.     MM_Version                                'system.mm'
  680.     MM_GetCfgPaths                        'system.mm'
  681.  
  682.     call Include_Lib('rexxsupport')
  683. return
  684.  
  685.  
  686. IOerr:
  687.     return_code        = 20
  688.     error_line    = sigl
  689.     error_msg            = 'IO-error' rc 'at line' sigl '['errortext(rc)']')
  690.     rc                        = 0
  691. signal Exit
  692.  
  693.  
  694. Log: procedure Expose system.
  695.  
  696.     parse arg text, pre, level
  697.  
  698.     if ~datatype(level, 'N') then level = system.prg.loglevel
  699.  
  700.     tmp        = word('PRG MM', (pre~='')+1)
  701.     text    = system.tmp.logpre || pre' 'text
  702.  
  703.     MM_WriteLog 'text' level
  704. return
  705.  
  706.  
  707. Path: procedure
  708.  
  709.    parse arg path
  710.    if right(path,1) ~= '/' & right(path,1) ~= ':' then path = path'/'
  711. return path
  712.  
  713.  
  714. Parse_Args: procedure Expose system.
  715.  
  716.     parse arg args
  717.  
  718.     tpl        = system.cmdopts',?/S,'
  719.     args    = translate(args, '  ', '9'x)
  720.     p            = min(pos('/K', tpl), pos('/S', tpl))
  721.     p            = lastpos(',', left(tpl, p))
  722.     tpl        = substr(tpl, p+1) || left(tpl, max(p-1, 0))
  723.  
  724.     do while tpl~=''
  725.         parse var tpl template ',' tpl
  726.         parse var template keyword '/' .
  727.  
  728.         bool    = pos('/S',    template)>0
  729.         key        = pos('/K', template)>0
  730.         must    = pos('/A', template)>0
  731.         num        = pos('/N', template)>0
  732.  
  733.         select
  734.             when must then        system.arg.keyword    = '0'x
  735.             when bool    then        system.arg.keyword    = 0
  736.             when num    then        system.arg.keyword    = 0
  737.  
  738.             otherwise                    system.arg.keyword    = ''
  739.         end
  740.  
  741.         if bool | key    then    mode    = ~bool
  742.         else                                mode    = 2
  743.  
  744.         system.arg.keyword    = Get_Arg(keyword, mode, system.arg.keyword)
  745.  
  746.         if must & system.arg.keyword='0'x then
  747.             do
  748.                 tmp    = template 'missing!!!'
  749.  
  750.                 say
  751.                 say ' ***' tmp '***'
  752.  
  753.                 signal Usage
  754.             end
  755.  
  756.         if num & ~datatype(system.arg.keyword, 'N') then
  757.             do
  758.                 tmp    = 'Numeric value expected for' template', but is "'system.arg.keyword'"!!!'
  759.  
  760.                 say
  761.                 say ' ***' tmp '***'
  762.  
  763.                 signal Usage
  764.             end
  765.     end
  766.  
  767.     drop mode
  768.  
  769.     tmp    = '?'; if system.arg.tmp then signal Usage
  770.  
  771.     if args~='' then call Quit(10, 'Unknown option(s):' args)
  772.  
  773.     if system.arg.decode    then
  774.     if system.arg.encode | system.arg.area='' | system.arg.msg='' then signal Usage
  775.         else nop
  776.     else
  777.         do
  778.             upper system.arg.mode
  779.  
  780.             if ~system.arg.gui & system.arg.area=''                                            then signal Usage
  781.             if ~system.arg.gui & find('FS MIME UU', system.arg.mode)=0    then signal Usage
  782.  
  783.             if system.arg.infofile~=''    then
  784.                 do
  785.                     system.arg.infofile    = Expand_Path(system.arg.infofile)
  786.  
  787.                     if ~exists(system.arg.infofile)    then call Quit(11, system.arg.infofile 'does not exist!')
  788.                 end
  789.         end
  790.  
  791.     if system.arg.maxsize>0    then
  792.         if system.arg.maxsize<10000 then call Quit(11, 'Invalid value for MAXSIZE/K/N "'system.arg.maxsize'"!')
  793.         else
  794.             do
  795.                 tmp                                    = system.arg.mode
  796.                 system.tmp.maxsize    = system.arg.maxsize
  797.             end
  798.  
  799. return
  800.  
  801.  
  802. Quit:
  803.  
  804.     parse arg return_code, error_msg
  805.  
  806.     error_line    = 0
  807.     rc                        = 0
  808. signal Exit
  809.  
  810.  
  811. Read_Cfg: procedure Expose system.
  812.  
  813.     MM_ReadStem system.prg.cfg 'cfg'
  814.     if RC~=0 then call Quit(31, 'Unable to read' system.prg.cfg'!!!')
  815.  
  816.     call Log('Reading config...')
  817.  
  818.     cnt    = 0
  819.  
  820.     do l=0 to cfg.count-1
  821.         parse value strip(translate(cfg.l, ' ', '9'x)) with key args ';' .
  822.         key        = upper(strip(key))
  823.         args    = strip(args)
  824.  
  825.         select
  826.             when key='' then iterate
  827.  
  828.             when key='#FSDECODE'        then system.cmd.fs.decode        = args
  829.             when key='#FSENCODE'        then system.cmd.fs.encode        = args
  830.             when key='#FSMAXSIZE'        then
  831.                 if datatype(args, 'N') & args>=10000 then system.fs.maxsize    = args
  832.                 else call Quit(11, 'Invalid value "'args'" for #FSMAXSIZE at line' l'!')
  833.  
  834.             when key='#MIMEDECODE'    then system.cmd.mime.decode    = args
  835.             when key='#MIMEENCODE'    then system.cmd.mime.encode    = args
  836.             when key='#MIMEMAXSIZE'    then
  837.                 if datatype(args, 'N') & args>=10000 then system.mime.maxsize    = args
  838.                 else call Quit(11, 'Invalid value "'args'" for #MIMEMAXSIZE at line' l'!')
  839.  
  840.             when key='#UUDECODE'        then system.cmd.uu.decode        = args
  841.             when key='#UUENCODE'        then system.cmd.uu.encode        = args
  842.             when key='#UUMAXSIZE'        then
  843.                 if datatype(args, 'N') & args>=10000 then system.uu.maxsize    = args
  844.                 else call Quit(11, 'Invalid value "'args'" for #UUMAXSIZE at line' l'!')
  845.  
  846.             when key='#OUTDIR'            then system.prg.dir                    = path(args)
  847.  
  848.             when key='#NOCLEARNEW'    then nop
  849.             when key='#CLEARNEW'        then system.clearnew                = 1
  850.  
  851.             otherwise say '*** CFG-ERROR: Unknown keword "'key'" at line' l'!!!'
  852.         end
  853.  
  854.         cnt    = cnt+1
  855.     end
  856.  
  857.     if cnt~=11    then    call Quit(10, 'Required config-argument(s) missing!')
  858.  
  859.     system.tmpdir        = system.prg.dir || system.prg.name'/'
  860.     system.tmpfile    = system.prg.dir || system.prg.name'.tmp'
  861.  
  862. return
  863.  
  864.  
  865. Read_Msg: procedure Expose msg. system.
  866.  
  867.     parse arg area, nr, errtxt
  868.  
  869.     call Log('Processing' area', msg #'nr'...',, 4)
  870.  
  871.     MM_ReadMsg area nr 'msg'
  872.     if RC~=0 then call Quit(20, errtxt)
  873.  
  874.     MM_AddToStem 'system.msg' 'nr'
  875.  
  876. return
  877.  
  878.  
  879. Replace: procedure
  880.  
  881.     parse arg string,new,old
  882.  
  883.     do while index(string, old)>0
  884.         interpret "parse var string l '"old"' r"
  885.         string = l || new || r
  886.     end
  887.  
  888. return string
  889.  
  890.  
  891. Request_Choice: procedure Expose system.
  892.  
  893.     parse arg text, buttons, ret_vals
  894.  
  895.     title    = system.prg.name'-Requester'
  896.     text    = translate(Replace(text, '0A'x, '\n'), '1b'x, '\')
  897.  
  898.     if length(text)<40 then text = center(text, 40)
  899.  
  900.     MM_Requester title 'text' 'buttons'
  901.  
  902.     if rc=0 then rc=words(ret_vals)
  903.  
  904. return compress(word(ret_vals, rc), '_')
  905.  
  906.  
  907. Request_String: procedure Expose RC system.
  908.  
  909.     parse arg txt, value, force
  910.  
  911.     old        = value
  912.  
  913.     do until ~force
  914.         MM_StringReq '"'txt'"' 'value'
  915.         if RC=1    then call Quit(5, 'Aborted by user!')
  916.  
  917.         value    = strip(value)
  918.         force = force & value=''
  919.     end
  920.  
  921. return value
  922.  
  923.  
  924. Search_Encoded: procedure Expose msg. result. system.
  925.  
  926.     arg type, id
  927.  
  928.     result.    = 0
  929.  
  930.     MM_SearchInStem 'msg.text' 'result' system.type.ptrn.id 'NUM'
  931.  
  932.     result.found    = ''
  933.  
  934.     do n=0 to result.count-1
  935.         result.found    = result.found result.n
  936.     end
  937.  
  938.     result.found    = strip(result.found)
  939.  
  940. return result.count>0
  941.  
  942.  
  943. Search_Encoded_Files: procedure Expose msg. system.
  944.  
  945.     parse arg area, msgnr
  946.  
  947.     call Read_Msg(area, msgnr, 'Could not access' area', msg #'nr'!')
  948.  
  949.     select
  950.         when Search_Encoded('UU', 'BEGIN')    then
  951.             do
  952.                 dest    = system.tmpdir
  953.                 mode    = 'UU'
  954.             end
  955.  
  956.         when Search_Encoded('FS', 'BEGIN')    then
  957.             do
  958.                 dest    = ''
  959.                 mode    = 'FS'
  960.             end
  961.  
  962.         when Search_Encoded('MIME', 'BEGIN')    then
  963.             do
  964.                 dest    = system.tmpdir
  965.                 mode    = 'MIME'
  966.             end
  967.  
  968.         otherwise call Quit(10, 'Could not locate UU-, FS- or MIME-encoded files!')
  969.      end
  970.  
  971.     system.cmd.mode.decode    = Replace(Replace(system.cmd.mode.decode, system.tmpfile, '%e'), dest, '%d')
  972.  
  973.     MM_GetAreaInfo area 'system.ainfo'
  974.  
  975.     encoded.            = ''
  976.   encoded.start    = result.found
  977.  
  978.     if system.arg.gui then
  979.         do
  980.             tmp.0.0    = ''
  981.             tmp.0.1    = 'it'
  982.             tmp.1.0    = 's'
  983.             tmp.1.1    = 'them'
  984.             tmp            = result.count>1
  985.  
  986.             ret = Request_Choice('\c\nThis msg contains' result.count mode'-encoded file'tmp.tmp.0'.\n\n' ||,
  987.                         'Shall I decode' tmp.tmp.1 'to' system.prg.dir'?\n', '* _YES |_Path|  _NO  ', '1 2 0')
  988.  
  989.             select
  990.                 when ret=0  then        call Quit(5, 'Aborted by user!')
  991.  
  992.                 when ret=2    then
  993.                     do
  994.                         MM_FileReq 'system.prg.dir'
  995.                         if RC~=0    then    call Quit(5, 'Aborted by user!')
  996.  
  997.                         p    = max(lastpos(':', system.prg.dir), lastpos('/', system.prg.dir))
  998.                         if p>0    then system.prg.dir = left(system.prg.dir, p)
  999.  
  1000.                         if ~exists(system.prg.dir) then call Quit(31, system.prg.dir 'does not exist!')
  1001.                     end
  1002.  
  1003.                 otherwise nop
  1004.             end
  1005.         end
  1006.  
  1007.     call Log('Found' result.count mode'-encoded file(s).')
  1008.  
  1009.     line.    = -1
  1010.  
  1011.     do x=1 while encoded.start~=''
  1012.         parse var encoded.start line.start encoded.start
  1013.  
  1014.         call Search_Encoded(mode, 'END')
  1015.  
  1016.         do while line.ende<line.start & line.ende~=0
  1017.             parse var result.found line.ende result.found
  1018.  
  1019.             if ~datatype(line.ende, 'N') then line.ende=0
  1020.         end
  1021.  
  1022.         if line.ende=0    then    line.ende    = -1
  1023.  
  1024.         call Get_Encoded_File(mode, area, msgnr, line.start, line.ende, 1, system.mode.offs.begin)
  1025.         system.ok    = Decode_File(mode, system.tmpfile)=0
  1026.     end
  1027.  
  1028. return
  1029.  
  1030.  
  1031. Send_File: procedure Expose msg. system.
  1032.  
  1033.     arg mode
  1034.  
  1035.     call Log(mode'-encoding "'msg.send'"...')
  1036.  
  1037.   cmd    = Replace(Replace(system.cmd.mode.encode, msg.send, '%d'), system.tmpfile, '%e')
  1038.     ret    = Command(cmd)
  1039.  
  1040.     parse value statef(system.tmpfile) with . size .
  1041.  
  1042.     if ret>0 | ~datatype(size, 'N') then call Quit(20, 'Unable to' mode'-encode "'msg.send'"!')
  1043.  
  1044.     max    = (size%system.mode.maxsize)+1
  1045.  
  1046.     if max>1    then    msglen    = size%max
  1047.     else                        msglen    = system.mode.maxsize
  1048.  
  1049.     if system.arg.gui then
  1050.         if Request_Choice('\cShall I post\n\n\1'msg.send'\n(Encoded' size 'bytes =' max 'msgs)\0\n\nin area' msg.area'?',,
  1051.             '* _YES |  NO  ', '0 1') then call Quit(5, 'Posting aborted by user!')
  1052.  
  1053.     add                            = 1
  1054.     maxlen                    = length(max)
  1055.     msg.count                = 0
  1056.     msg.head.count    = 0
  1057.     msg.text.count    = 0
  1058.     msg.foot.count    = 0
  1059.     msg.tear                = system.prg.id
  1060.     subject                    = msg.subj
  1061.  
  1062.     if system.arg.infofile~=''    then
  1063.         do
  1064.             parse value statef(system.arg.infofile)'0 0' with . tmp .
  1065.  
  1066.             if tmp+size>system.mode.maxsize    then
  1067.                 do
  1068.                     add                = 0
  1069.                     msg.count    = -1
  1070.                     msg.file    = system.arg.infofile
  1071.  
  1072.                     call Write_Msg(0)
  1073.                 end
  1074.             else MM_ReadStem system.arg.infofile 'msg.text'
  1075.  
  1076.             if system.arg.delinfofile    then call delete(system.arg.infofile)
  1077.         end
  1078.  
  1079.     MM_ReadStem system.tmpfile 'uufile'
  1080.  
  1081.     msg.file            = system.tmpfile'2'
  1082.     cnt                        = 0
  1083.  
  1084.     if add then    call Add_Text()
  1085.  
  1086.     do n=0 to uufile.count-1
  1087.         cnt = cnt+length(uufile.n)+1
  1088.  
  1089.         if cnt>msglen then call Write_Msg(1)
  1090.  
  1091.         call Add_Text(uufile.n)
  1092.     end
  1093.  
  1094.     if msg.text.count>0    then call Write_Msg(1)
  1095.  
  1096.     if system.arg.gui        then call Request_Choice('\c\nFile successfully' mode'-encoded!.\n', '*  _OK  ', '0')
  1097.  
  1098.     call delete(system.tmpfile)
  1099.     call delete(msg.file)
  1100.  
  1101. return
  1102.  
  1103.  
  1104. Syntax:
  1105.     return_code        = 40
  1106.     error_line    = sigl
  1107.     error_msg            = 'Syntax-error' rc 'at line' sigl '['errortext(rc)']'
  1108.     rc                        = 0
  1109. signal Exit
  1110.  
  1111.  
  1112. Usage:
  1113.  
  1114.     rx.            = ''
  1115.     rx.0.0    = '[rx] '
  1116.     rx.0.1    = '[.rexx]'
  1117.     m                =    pos('/e', system.prg.ver)>0
  1118.     tmp            = rx.m.0 || system.prg.name || rx.m.1
  1119.  
  1120.     say
  1121.     say 'Usage:' tmp 'ENCODE/S/A,GUI/S,MODE/K/A,AREA/K,FILE/K,FLAGS/K,FROM/K,FROMADDR/K,ORIGIN/K,',
  1122.                                      'SUBJ/K,TO/K,TOADDR/K,INFOFILE/K,DELINFOFILE/S,MAXSIZE/K/N'
  1123.     say '   or:' tmp 'DECODE/S/A,GUI/S,AREA/A/K,MSG/A/K/N'
  1124.     say
  1125.  
  1126. call Quit(0, 'Usage requested.')
  1127.  
  1128.  
  1129. Write_Line: procedure Expose msg. system.
  1130.  
  1131.     parse arg nr, check
  1132.  
  1133.     if check then
  1134.         do
  1135.             tmp    = length(compress(msg.text.nr))
  1136.  
  1137.             if tmp~=length(msg.text.nr)    then return 0
  1138.             if tmp~=msg.enclen                    then return 0
  1139.         end
  1140.  
  1141.     call writeln(out, msg.text.nr)
  1142.  
  1143. return 1
  1144.  
  1145.  
  1146. Write_Msg:
  1147.  
  1148.     parse arg write
  1149.  
  1150.     msg.count    = msg.count+1
  1151.     msg.subj    = subject '['right(msg.count, maxlen, '0')'/'max']'
  1152.  
  1153.     call Add_Text()
  1154.     if system.is_mail then call Add_Text('---' system.prg.id'  'system.prg.cr)
  1155.  
  1156.     call Log('Posting' msg.subj 'in area' msg.area'...')
  1157.  
  1158.     if write then MM_WriteStem    msg.file 'msg.text'
  1159.  
  1160.     MM_WriteMsg        msg.area 'msg'
  1161.  
  1162.   cnt                         = 0
  1163.     msg.text.count    = 0
  1164.  
  1165.     call Add_Text()
  1166.  
  1167. return
  1168.  
  1169.  
  1170.